import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Scanner;
import java.net.*;
public class Client5_6 {
    public static void main(String[] args) {
        String mode = "AES";
        //客户端让用户输入中缀表达式，然后把中缀表达式调用MyBC.java的功能转化为后缀表达式，把后缀表达式通过网络发送给服务器
        Scanner scanner = new Scanner(System.in);
        Socket mysocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            mysocket = new Socket("127.0.0.1", 2010);
            in = new DataInputStream(mysocket.getInputStream());
            out = new DataOutputStream(mysocket.getOutputStream());
            System.out.println("请输入要计算的题目：");
            String formula = scanner.nextLine();
            String regex = ".*[^0-9|+|\\-|*|÷|(|)|\\s|/].*";
            if (formula.matches(regex)) {
                System.out.println("输入了非法字符");
                System.exit(1);
            }
            String output = "";
            MyBC myBC = new MyBC();
            try {
                //中缀转后缀
                output = myBC.getEquation(formula);
            } catch (ExprFormatException e) {
                System.out.println(e.getMessage());
                System.exit(1);
            }
            //使用AES进行后缀表达式的加密
            KeyGenerator kg = KeyGenerator.getInstance(mode);
            kg.init(128);
            SecretKey k = kg.generateKey();//生成密钥
            byte mkey[] = k.getEncoded();
            Cipher cp = Cipher.getInstance(mode);
            cp.init(Cipher.ENCRYPT_MODE, k);
            byte ptext[] = output.getBytes("UTF8");
            byte ctext[] = cp.doFinal(ptext);

            //将加密后的后缀表达式传送给服务器
            String out1 = B_H.parseByte2HexStr(ctext);
            out.writeUTF(out1);

            //创建客户端DH算法公、私钥
            KeyPair keyPair = Key_DH5_6.createPubAndPriKey();
            PublicKey pbk = keyPair.getPublic();//Client公钥
            PrivateKey prk = keyPair.getPrivate();//Client私钥

            //将公钥传给服务器
            byte cpbk[] = pbk.getEncoded();
            String CpubKey = B_H.parseByte2HexStr(cpbk);
            out.writeUTF(CpubKey);
            Thread.sleep(1000);

            //接收服务器公钥
            String SpubKey = in.readUTF();
            byte[]spbk = H_B.parseHexStr2Byte(SpubKey);
            KeyFactory kf = KeyFactory.getInstance("DH");
            PublicKey serverPub = kf.generatePublic(new X509EncodedKeySpec(spbk));

            //生成共享信息，并生成AES密钥
            SecretKeySpec key = KeyAgree5_6.createKey(serverPub,prk);

            //对加密后缀表达式的密钥进行加密，并传给服务器
            cp.init(Cipher.ENCRYPT_MODE, key);
            byte ckey[] = cp.doFinal(mkey);
            String Key = B_H.parseByte2HexStr(ckey);
            out.writeUTF(Key);

            //接收服务器回答
            String s = in.readUTF();
            System.out.println("客户收到服务器的回答：" + s);
        } catch (Exception e) {
            System.out.println("服务器已断开" + e);
        }
    }
}

